#include <QDesktopServices>
#include <QGraphicsView>
#include <QApplication>
#include <QFileDialog>
#include <QLibrary>
#include <QDebug>

#define UIKIT_SIMULATOR
#include <UIKit/UIApplication.h>
#include <UIKit/UIWindow.h>
#include <UIKit/UIDevice.h>

#include "ui_devicesimulatorwindow.h"
#include "devicesimulatorwindow.h"

#define DEVICE_PADDING      QSize(8, 8)

// ===========================================================================
//  PRIVATE Class
// ===========================================================================
class THDeviceSimulatorWindowPrivate {
    public:
        Ui::DeviceSimulatorWindow ui;
        QGraphicsView *view;
        qreal angle;

    public:
        UIDeviceOrientation orientation (void) const;
        void updateDeviceViewOrientation (void);
};

UIDeviceOrientation THDeviceSimulatorWindowPrivate::orientation (void) const {
    if (angle == 0)
        return(UIDeviceOrientationLandscapeLeft);

    if (angle == 90)
        return(UIDeviceOrientationPortrait);

    if (angle == 180)
        return(UIDeviceOrientationLandscapeRight);

    if (angle == 270)
        return(UIDeviceOrientationPortraitUpsideDown);

    return(UIDeviceOrientationUnknown);
}

void THDeviceSimulatorWindowPrivate::updateDeviceViewOrientation (void) {
    QRect rect = QRect(QPoint(0, 0), kUIDeviceScreenSize);
    UIWindow *window = UIApplication::sharedApplication()->keyWindow();
    if (window != NULL) window->setSceneRect(rect);
    view->setSceneRect(rect);
    view->setFixedSize(kUIDeviceScreenSize + DEVICE_PADDING);
}

// ===========================================================================
//  PUBLIC Constructor/Destructor
// ===========================================================================
THDeviceSimulatorWindow::THDeviceSimulatorWindow (QWidget *parent)
    : QMainWindow(parent), d(new THDeviceSimulatorWindowPrivate)
{
    d->ui.setupUi(this);
    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    d->angle = 90;

    // Switch App
    connect(UIApplication::sharedApplication(), 
            SIGNAL(keyWindowChanged(UIWindow *)),
            this, SLOT(keyWindowChanged(UIWindow *)));

    UIDevice *device = UIDevice::currentDevice();
    d->view = new QGraphicsView(new QGraphicsScene);
    d->view->setMouseTracking(true);
    d->view->centerOn(0, 0);
    d->view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    d->view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    d->view->setBackgroundBrush(Qt::black);
    d->view->setMouseTracking(true);
    d->updateDeviceViewOrientation();
    setMaximumSize(d->view->size());
    setCentralWidget(d->view);

    // File Actions...
    connect(d->ui.actionLoadApp, SIGNAL(triggered()), 
            this, SLOT(loadAppDialog()));

    // Device Actions...
    connect(d->ui.actionRotateLeft, SIGNAL(triggered()), 
            this, SLOT(rotateLeft()));
    connect(d->ui.actionRotateRight, SIGNAL(triggered()),
            this, SLOT(rotateRight()));
    connect(d->ui.actionZoomSmaller, SIGNAL(triggered()),
            this, SLOT(zoomSmaller()));
    connect(d->ui.actionZoomNormal, SIGNAL(triggered()),
            this, SLOT(zoomNormal()));
    connect(d->ui.actionZoomLarger, SIGNAL(triggered()),
            this, SLOT(zoomLarger()));
    connect(d->ui.actionPowerButton, SIGNAL(triggered()),
            device, SLOT(pressPowerButton()));
    connect(d->ui.actionAuxButton, SIGNAL(triggered()),
            device, SLOT(pressAuxButton()));

    // Help Actions...
    connect(d->ui.actionAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));

}

THDeviceSimulatorWindow::~THDeviceSimulatorWindow() {
    delete d;
}

// ===========================================================================
//  PUBLIC Properties
// ===========================================================================
void THDeviceSimulatorWindow::loadApp (const QString& fileName) {
    UIApplication::sharedApplication()->load(fileName);
}

// ===========================================================================
//  PUBLIC Properties
// ===========================================================================

// ===========================================================================
//  PUBLIC Slots (File Actions)
// ===========================================================================
void THDeviceSimulatorWindow::loadAppDialog (void) {
    QString fileName = QFileDialog::getOpenFileName(this, 
                                   tr("Open Device App"),
            QDesktopServices::storageLocation(QDesktopServices::HomeLocation),
                    tr("Device App (*.so *.dll *.*)"));

    if (!fileName.isEmpty())
        loadApp(fileName);
}

// ===========================================================================
//  PUBLIC Slots (Device Actions)
// ===========================================================================
void THDeviceSimulatorWindow::rotateLeft (void) {
    d->angle = (d->angle == 270) ? 0 : (d->angle + 90);
    UIDevice::currentDevice()->setOrientation(d->orientation());
    d->updateDeviceViewOrientation();
    setMaximumSize(d->view->size());
    update();
}

void THDeviceSimulatorWindow::rotateRight (void) {
    d->angle = (d->angle == 0) ? 270 : (d->angle - 90);
    UIDevice::currentDevice()->setOrientation(d->orientation());
    d->updateDeviceViewOrientation();
    setMaximumSize(d->view->size());
    update();
}

void THDeviceSimulatorWindow::zoomNormal (void) {
    d->view->resetTransform();
}

void THDeviceSimulatorWindow::zoomLarger (void) {
    d->view->scale(1.1, 1.1);
}

void THDeviceSimulatorWindow::zoomSmaller (void) {
    d->view->scale(0.9, 0.9);
}

// ===========================================================================
//  PRIVATE Slots
// ===========================================================================
void THDeviceSimulatorWindow::keyWindowChanged (UIWindow *window) {
    window->setSceneRect(QRect(QPoint(0, 0), kUIDeviceScreenSize));
    d->view->setScene(window);
}

